<template>
  <view class="content">
    <!-- #ifndef H5 -->
    <u-navbar back-text="返回" title="NFT" :title-size="28" back-icon-color="#fff" :background="{ background: '#FE572A' }"
      :back-text-style="{ color: '#fff' }" title-color="#fff">
      <template v-slot:right>
        <view class="u-m-r-20">
          <u-icon name="scan" color="#fff" size="40" @click="scanCode"></u-icon>
        </view>
      </template>
    </u-navbar>
    <!-- #endif -->
    <!-- #ifdef H5 -->
    <u-navbar back-text="返回" title="NFT" :title-size="28" back-icon-color="#fff" :background="{ background: '#FE572A' }"
      :back-text-style="{ color: '#fff' }" title-color="#fff">
    </u-navbar>
    <!-- #endif -->
    <view class="position-fixed left-0 w-100" :style="{ top: topFixed, 'z-index': 100 }">
      <u-tabs :list="tabs" :is-scroll="false" activeColor="var(--mainColor)" :current="current" @change="change"></u-tabs>
    </view>
    <view>
      <view class="picker-grid" v-if="query.status == 1">
        <view class="u-flex-1">
          <uni-data-select v-model="query.type" :localdata="types" :clear="false"></uni-data-select>
        </view>
        <view class="u-flex-1">
          <uni-data-select v-model="query.sort" :localdata="range" :clear="false"></uni-data-select>
        </view>
      </view>
      <view class="picker-grid" v-if="query.status == 2">
        <view class="u-flex-1">
          <uni-data-select v-model="query.type" :localdata="types" :clear="false"></uni-data-select>
        </view>
        <view class="u-flex-1">
          <uni-data-select v-model="query.sort" :localdata="timeRange" :clear="false"></uni-data-select>
        </view>
      </view>
      <view class="card-content">
        <mescroll-body :up="upOption" ref="mescrollRef" :bottombar="false" @init="mescrollInit" @down="downCallback"
          @up="upCallback">
          <u-checkbox-group>
            <view class="card-grids">
              <view class="card-grid" v-for="item in lists" :key="item.id" @click="handleViewDetail(item)">
                <view @click.stop class="card-checkbox" v-if="query.status == 1">
                  <u-checkbox active-color="#FE572A" @change="checkboxChange" :name="item.id" v-model="item.checked" />
                </view>
                <image v-if="item.nft_image" :src="item.nft_image" mode="aspectFill" class="card-img" />
                <image v-else src="../static/images/zs.jpg" mode="aspectFill" class="card-img" />
                <view class="card-box" v-show="query.status == 1">
                  <view class="card-value">贡献值:{{ item.contribution_total || 0 }}</view>
                </view>
                <view class="card-box" v-show="query.status == 2">
                  <view class="card-value u-text-left">贡献值:{{ item.contribution_total || 0 }}</view>
                  <view class="card-value u-text-left u-m-t-20">
                    累计获得：{{ item.mining_income_total || 0 }} 消费积分</view>
                </view>
              </view>
            </view>
          </u-checkbox-group>
        </mescroll-body>
      </view>
      <view class="fixed-btn" v-show="query.status == 1 && checkBoxList.length">
        <view v-if="checkBoxList.length" class="qr-box">
          <button class="cancel-btn" @click="handleCancelCheck">取消</button>
          <button @click="handleConfirmAll">铸造</button>
        </view>
      </view>
    </view>
    <u-popup v-model="casting" mode="center" border-radius="14" width="720rpx" @close="casting = false">
      <view class="u-p-20 popup-box">
        <view>
          <view class="detail-info gray-bg">
            <view class="flex align-center justify-between item">
              <text>NFT数量</text>
              <text>{{ checkBoxList.length || 1 }}</text>
            </view>
            <view class="flex align-center justify-between item">
              <text>剩余贡献值</text>
              <text>{{ totalContribute || 0 }}</text>
            </view>
            <!-- <view class="flex align-center justify-between item" >
              <text>Gas费</text>
              <text>{{ estimatedGas || 0 }} 积分</text>
            </view> -->
          </view>
          <button class="btn-primary" @click="handleSubmitMint">铸造</button>
        </view>
        <view class="popup-header">
          <text>铸造</text>
          <view class="popup-close" @click="casting = false">
            <uni-icons type="closeempty" size="20"></uni-icons>
          </view>
        </view>
      </view>
    </u-popup>
    <u-popup v-model="walletshow" mode="center" border-radius="14" width="720rpx" @close="handleCloseWallet">
      <view class="u-p-20 popup-box">
        <view>
          <view class="detail-info">
            <input type="password" v-model="passwordInput" placeholder="请输入钱包密码" style="border-radius: 16rpx;"
              class="border u-p-16 u-m-t-20 font-26" />
          </view>
          <button class="btn-primary" @click="handlegift">确定</button>
        </view>
        <view class="popup-header">
          <text>钱包密码</text>
          <view class="popup-close" @click="walletshow = false">
            <uni-icons type="closeempty" size="20"></uni-icons>
          </view>
        </view>
      </view>
    </u-popup>
  </view>
</template>

<script>
import {
  mapGetters,
} from 'vuex'
import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
import {
  NftWalletApi
} from "@/api/modules/NftWallet.js"
import {
  validateWalletPassword,
  scanPayment,
  copyDownloadUrl,
  decryptAES
} from "@/common/utils/utils.js"
import {
  ethers
} from "ethers";
import {
  ServerWalletApi
} from "@/api/modules/ServerWallet.js"
import BLOCK_CONFIG from "@/config/block.js";
export default {
  mixins: [MescrollMixin],
  data () {
    return {
      copyDownloadUrl,
      scanPayment,
      walletshow: false,
      casting: false,
      query: {
        type: 1,
        status: 1,
        sort: 1,
      },
      upOption: {
        page: {
          size: 20
        }
      },
      lists: [],
      timeValue: 0,
      typeValue: 0,
      types: [
      //   {
      //   value: '',
      //   text: "全部类型"
      // },
      {
        value: 1,
        text: "订单NFT"
      },
      {
        value: 2,
        text: "商品NFT"
      },
      ],
      value: 0,
      range: [{
        value: 1,
        text: "按贡献值"
      },
      {
        value: 2,
        text: "按获得时间"
      }
      ],
      timeRange: [{
        value: 3,
        text: "按收益↑"
      },
      {
        value: 4,
        text: "按收益↓"
      },
      ],
      tabs: [{
        name: "待铸造"
      },
      {
        name: "已获得"
      },
      ],
      current: 0,
      checkBoxList: [],
      passwordInput: "",
      estimatedGas: "",
      signData: {
        sign: "",
        nftId: 0
      }
    }
  },
  watch: {
    query: {
      handler () {
        this.mescroll.resetUpScroll()
      },
      deep: true
    }
  },
  computed: {
    ...mapGetters({
      nftConfig: "user/getNftConfig"
    }),
    topFixed () {
      return this.windowTop + 'px'
    },
    totalContribute () {
      return this.checkBoxList.reduce((sum, id) => {
        const item = this.lists.find(obj => obj.id === id);
        return sum + (item ? item.contribution_total : 0);
      }, 0);
    }
  },
  mounted () {
    this.handleFetchGasPrice()
  },
  methods: {
    async handleFetchGasPrice () {
      const res = await NftWalletApi.getGasPrice()
      if (res.code == 1)
      {
        this.estimatedGas = res.data.cost
      } else
      {
        this.$Toast(res.msg)
      }
    },
    handleCloseWallet () {
      this.walletshow = false
      this.passwordInput = ""
    },
    async handlegift () {
      this.$ShowLoading()
      if (!this.passwordInput.trim()) return this.$HideLoading()
      const res = await validateWalletPassword(this.passwordInput, this.walletAddress)
      this.$HideLoading()
      if (res)
      {
        if (res.code == 1)
        {
          await this.mintTokens()
        } else
        {
          this.$Toast(res.msg)
        }
      }
    },
    async mintTokens () {
      this.$ShowLoading()
      try
      {
        const {
          name
        } = BLOCK_CONFIG.rpcInfo;
        const chainId = this.nftConfig.chain_id
        const res = await NftWalletApi.getUserWallet();
        if (res.code !== 1)
        {
          this.$Toast(res.msg);
          this.$HideLoading()
          return;
        }
        const {
          sk_key,
          password
        } = res.data;
        const result = await NftWalletApi.decrypt({
          data: password
        });
        if (result.code !== 1)
        {
          this.$Toast(result.msg);
          this.$HideLoading()
          return;
        }
        const privateKey=  await decryptAES(sk_key,result.data)
        try
        {
          let signer = new ethers.Wallet(privateKey);
          const toIndex = this.nftConfig.nft.findIndex(item => item.name == "LK")
          const ABI = this.nftConfig.nft[toIndex].abi
          const contractInterface = new ethers.Interface(ABI)
          this.checkBoxList.forEach(async (item) => {
            const nft_codeItem = this.lists.find(list => list.id === item)
            if (!nft_codeItem?.nft_code) return this.$Toast("Nft Code为空")
            const resd = await NftWalletApi.nftMint(nft_codeItem.nft_code,nft_codeItem.type)
            if (resd.code == 1)
            {
              const {
                data
              } = resd
              if (typeof data === 'string') return this.$Toast(resd.msg)
              const {
                nft_id,
                nonce,
                signature
              } = data
              const txData = contractInterface.encodeFunctionData('mintNFT', [nft_id,
                nonce, signature
              ])
              const result = await uni.request({
                url: this.nftConfig.rpcurl,
                method: 'POST',
                data: {
                  jsonrpc: "2.0",
                  method: "eth_getTransactionCount",
                  params: [signer.address, "latest"],
                  id: 1
                },
              })
              const nonces = Number(result[1].data.result)
              const gasPriceRes = await ServerWalletApi.getWalletGasPrice()
              const tx = {
                nonce: nonces,
                gasPrice: ethers.parseUnits(gasPriceRes.data.gas_price_gwei,
                  "gwei"),
                gasLimit: 1000000,
                to: this.nftConfig.nft[toIndex].contract,
                value: ethers.parseEther("0"),
                data: txData,
                chainId: chainId
              }
              try
              {
                const signedTx = await signer.signTransaction(tx)
                const resu = await uni.request({
                  url: this.nftConfig.rpcurl,
                  method: 'POST',
                  data: {
                    jsonrpc: "2.0",
                    method: "eth_sendRawTransaction",
                    params: [signedTx],
                    id: 2
                  },
                })
                if (resu[1].data.error)
                {
                  this.$Toast("交易失败")
                } else if (resu[1].data.result)
                {
                  const hash = resu[1].data.result
                  await this.updateBackendStatus(hash,nft_codeItem.type);
                }
              } catch
              {
                this.$Toast("交易失败")
              } finally
              {
                this.$HideLoading()
              }
            } else
            {
              this.$Toast(resd.msg)
            }
          })
        } catch (error)
        {
          console.log(error)
          this.$Toast("铸造失败")
        }
      } catch (error)
      {
        this.$Toast("发生错误，请稍后再试");
      }
    },
    async updateBackendStatus (hashs,type) {
      this.$ShowLoading()
      const ids = this.checkBoxList.join(',')
      const res = await NftWalletApi.updateMintStatus(ids, hashs,type)
      this.$HideLoading()
      if (res.code == 1)
      {
        this.passwordInput = ""
        this.walletshow = false
        this.casting = false
        uni.showModal({
          title: "NFT铸造成功",
          showCancel: false,
          success: (res) => {
            if (res.confirm)
            {
              this.checkBoxList = []
              this.mescroll.resetUpScroll()
            }
          },
        })
      } else
      {
        this.$Toast(res.msg)
      }
    },
    checkboxChange (e) {
      if (e.value)
      {
        this.checkBoxList.push(e.name)
      } else
      {
        this.checkBoxList = this.checkBoxList.filter(item => item !== e.name);
      }
    },
    handleCancelCheck () {
      this.checkBoxList = []
      this.lists.map(item => {
        item.checked = false
      })
    },
    async handleConfirmAll () {
      if (!this.checkBoxList.length) return
      const nft_ids = this.checkBoxList.join(",")
      // #ifdef MP-WEIXIN
      uni.showModal({
        title: "操作需要钱包功能",
        content: "小程序版本不支持钱包，仅供查看,您可在APP中进行操作",
        cancelText: "下载APP",
        success: (res) => {
          if (res.cancel)
          {
            this.copyDownloadUrl()
          }
        }
      })
      // #endif
      // #ifndef MP-WEIXIN
      this.handleConfirmMint(nft_ids)
      // #endif
    },
    handleSubmitMint () {
      this.walletshow = true
      this.casting = false
    },
    handleConfirmMint (nft_ids) {
      this.casting = true
    },
    handleViewDetail (item) {
      uni.navigateTo({
        url: `/pages/mine/mineBalance/nft/detail?id=${item.id}&type=${item.type}`
      })
    },
    downCallback () {
      this.mescroll.resetUpScroll()
    },
    upCallback (page) {
      const {
        num,
        size
      } = page
      this.handleFetchNft(num, size)
    },
    back () {
      uni.navigateBack({
        delta: 1
      })
    },
    scanCode () {
      uni.scanCode({
        success: (res) => {
          const data = JSON.parse(res.result)
          const type = data.type || ''
          if (type == 'merch')
          {
            this.scanPayment(data)
          } else if (type == 'goods_nft')
          {
            this.scanGoods(data)
          }
        }
      });
    },
    scanGoods ({ goods_nft_id, _id }) {
      uni.navigateTo({
        url: `/pages/mine/mineBalance/nft/detail?id=${goods_nft_id}&type=goods&_id=${_id}`
      })
    },
    async handleFetchNft (num, size) {
      this.$ShowLoading()
      const params = {
        ...this.query,
        page: num,
        pageSize: size
      }
      const res = await NftWalletApi.getNftList(params)
      this.$HideLoading()
      if (res.code == 1)
      {
        const {
          data,
          totalpage
        } = res.data
        if (num == 1) this.lists = [];
        this.lists = this.lists.concat(data)
        if (this.lists.length)
        {
          this.lists.forEach(item => {
            item.checked = false
          })
        }
        this.mescroll.endByPage(data.length, totalpage)
      } else
      {
        this.$Toast(res.msg)
        this.mescroll.endErr()
      }
    },
    change (e) {
      this.current = e
      this.query.status = Number(e) + 1
      if (this.query.status == 2)
      {
        this.query.sort = 3
      } else
      {
        this.query.sort = 1
      }
    }
  }
}
</script>

<style scoped lang="scss">
.content {
  background-color: #fff;
  min-height: 100vh;
}

.abs-scan {
  position: fixed;
  right: 14rpx;
  top: 14rpx;
  z-index: 999
}

.picker-grid {
  margin: 100rpx 20rpx 20rpx 20rpx;
  display: flex;
  gap: 32rpx;
}

.fixed-btn {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 32rpx;
  border-top: 1px solid #eaeaea;
  background-color: #fff;
  z-index: 2;

  button {
    background-color: var(--mainColor);
    color: white;
    display: block;
    font-size: 30rpx;
  }
}

.card-content {
  padding-bottom: 100rpx;
}

.card-grids {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 32rpx;
  padding: 20rpx;
  position: relative;
}

.card-checkbox {
  position: absolute;
  top: 10rpx;
  right: 10rpx;
  z-index: 1;
}

.card-grid {
  border: 1px solid #eaeaea;
  border-radius: 16rpx;
  overflow: hidden;
  position: relative;
}

.card-img {
  width: 100%;
  height: 360rpx;
}

.card-box {
  padding: 20rpx;
  text-align: center;
  font-size: 28rpx;
}

.zz-box {
  min-height: 61.32rpx;
  margin-top: 20rpx;
}

.zz-btn {
  background-color: var(--mainColor);
  color: white;
  display: block;
  font-size: 24rpx;
}

.qr-box {
  display: flex;
  gap: 40rpx;
  align-items: center;

  button {
    flex: 1;
  }

  .cancel-btn {
    background-color: #fff;
    border: 1px solid var(--mainColor);
    color: var(--mainColor);
  }
}

.popup-box {
  position: relative;
}

.popup-header {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  padding: 20rpx;
  background-color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;

  text {
    font-size: 28rpx;
  }

  .popup-close {
    position: absolute;
    top: 50%;
    right: 20rpx;
    transform: translateY(-50%);
  }
}

.btn-primary {
  font-size: 28rpx;
  color: #fff;
  background-color: var(--mainColor);
  margin-top: 80rpx;
}

.detail-info {
  margin-top: 40rpx;
  border-radius: 16rpx;
  padding: 40rpx;
}

.gray-bg {
  background: rgba(0, 0, 0, 0.02);
}

.item {
  margin-bottom: 40rpx;

  text {
    color: #333;
    font-size: 32rpx;
  }

  text:first-child {
    color: #999;
    font-size: 28rpx;
  }

  &:last-child {
    margin-bottom: 0;
  }
}

.u-checkbox-group {
  display: block !important;
}

::v-deep.u-checkbox__label {
  display: none !important;
}</style>